package com.blackhorse.service.program;

import com.blackhorse.dao.AccountDao;
import com.blackhorse.domain.Account;
import com.blackhorse.service.AccountService;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

/**
 * 采用编程式事务控制的Service（实际开发很少使用，了解即可）
 * 在每个业务逻辑方法体中添加TransactionTemplate事务模板对象的execute方法
 * 参数传递TransactionCallback接口的实现类对象，并在doInTransaction方法中重写业务逻辑
 */
public class AccountServiceImplWithTransactionTemplate implements AccountService {

    private AccountDao accountDao;
    private TransactionTemplate transactionTemplate;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }

    @Override
    public Account findAccountById(int id) {
        //使用spring的事务模板对象进行编程式事务控制
        return transactionTemplate.execute(new TransactionCallback<Account>() {
            @Override
            public Account doInTransaction(TransactionStatus status) {
                return accountDao.findAccountById(id);
            }
        });
    }

    @Override
    public void transfer(String sourceName, String targetName, float money) {
        //使用spring的事务模板对象进行编程式事务控制
        transactionTemplate.execute(new TransactionCallback<Object>() {
            @Override
            public Object doInTransaction(TransactionStatus status) {
                Account srcAccount = accountDao.findAccountByName(sourceName);
                Account tarAccount = accountDao.findAccountByName(targetName);

                srcAccount.setMoney(srcAccount.getMoney() - money);
                tarAccount.setMoney(tarAccount.getMoney() + money);

                accountDao.updateAccount(srcAccount);
                //如果这里出现异常，转账金额将不再守恒
                int a = 1/0;
                accountDao.updateAccount(tarAccount);
                return null;
            }
        });

    }
}
